# -*- coding: UTF-8 -*-
"""
@Project ：swift-forge-engine 
@File    ：log_conf.py
@IDE     ：PyCharm 
@Author  ：Tony.Gan
@Date    ：2025/2/18 22:02 
@Des     ：
"""
import inspect
import logging
import os

from sys import stderr, stdout

from asgi_correlation_id import correlation_id
from loguru import logger

from App.config import path_conf
from App.config.conf import settings


class InterceptHandler(logging.Handler):
    """
    这是一个自定义的日志处理器，用于将 Python 标准库 logging 的日志记录转发到 loguru 的日志系统中
    """
    def emit(self, record: logging.LogRecord):
        try:
            level = logger.level(record.levelname).name
        except ValueError:
            level = record.levelno

        frame, depth = inspect.currentframe(), 0
        while frame and (depth == 0 or frame.f_code.co_filename == logging.__file__):
            frame = frame.f_back
            depth += 1

        logger.opt(depth=depth, exception=record.exc_info).log(level, record.getMessage())


def setup_logging():
    """
    配置日志系统，将标准库 logging 的日志记录转发到 loguru，并设置日志的输出格式和过滤器。
    :return:
    """
    logging.root.handlers = [InterceptHandler()]
    logging.root.setLevel(settings.LOG_ROOT_LEVEL)

    for name in logging.root.manager.loggerDict.keys():
        logging.getLogger(name).handlers = []
        if 'uvicorn.access' in name or 'watchfiles.main' in name:
            logging.getLogger(name).propagate = False
        else:
            logging.getLogger(name).propagate = True

    logger.remove()

    def correlation_id_filter(record) -> bool:
        cid = correlation_id.get(settings.LOG_CID_DEFAULT_VALUE)
        record['correlation_id'] = cid[: settings.LOG_CID_UUID_LENGTH]
        return True

    logger.configure(
        handlers=[
            {
                'sink': stdout,
                'level': settings.LOG_STDOUT_LEVEL,
                'filter': lambda record: correlation_id_filter(record) and record['level'].no <= 25,
                'format': settings.LOG_STD_FORMAT,
            },
            {
                'sink': stderr,
                'level': settings.LOG_STDERR_LEVEL,
                'filter': lambda record: correlation_id_filter(record) and record['level'].no >= 30,
                'format': settings.LOG_STD_FORMAT,
            },
        ]
    )


def set_customize_logfile():
    """
    将日志记录到文件中，并配置日志文件的轮转、保留和压缩策略
    :return:
    """
    log_path = path_conf.LOG_DIR
    if not os.path.exists(log_path):
        os.mkdir(log_path)

    log_stdout_file = os.path.join(log_path, settings.LOG_STDOUT_FILENAME)
    log_stderr_file = os.path.join(log_path, settings.LOG_STDERR_FILENAME)

    log_config = {
        'rotation': '10 MB',
        'retention': '30 days',
        'compression': 'tar.gz',
        'enqueue': True,
        'format': settings.LOG_FILE_FORMAT,
    }

    logger.add(
        str(log_stdout_file),
        level=settings.LOG_STDOUT_LEVEL,
        **log_config,
        backtrace=False,
        diagnose=False,
    )

    logger.add(
        str(log_stderr_file),
        level=settings.LOG_STDERR_LEVEL,
        **log_config,
        backtrace=True,
        diagnose=True,
    )


# 实力化log，方便在其他模块中使用
log = logger


